package com.example.demo2.utils;

import com.example.demo2.enums.ResponseCode;
import com.example.demo2.exception.BusinessException;
import com.example.demo2.reqvo.DlpReportReqVO;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * @author: chenshoumeng
 * @date: 2021/12/15 10:46
 */
@Slf4j
public class Utils {

  /**
   * 验签
   *
   * @param signatureKey  签名秘钥
   * @param reportReqVO 接收到的数据
   * @return
   */
  public static boolean signVerification(String signatureKey, DlpReportReqVO reportReqVO) {

    // 签名内容 signature_content
    String signatureContent = reportReqVO.getNonce() + "&" + reportReqVO.getTimestamp() + "&" + reportReqVO.getData();

    // 初始化消息认证码 MAC Message Authentication Code
    Mac mac = null;
    try {
      mac = Mac.getInstance( "HmacSHA256");
    } catch (NoSuchAlgorithmException e) {
      log.error("[验签] 初始化消息认证码 错误 signatureKey {}, data {} , e {}",signatureKey, reportReqVO, e);
      return false;
    }
    byte[] byteKey = signatureKey.getBytes( StandardCharsets.UTF_8); // 将签名秘钥转为 byte 格式
    SecretKeySpec secretKey = new SecretKeySpec( byteKey, "HmacSHA256");
    try {
      mac.init(secretKey);
    } catch (InvalidKeyException e) {
      log.error("[验签] mac.init 错误 signatureKey {}, data {} , e {}",signatureKey, reportReqVO, e);
      return false;
    }

    // 校验签名
    byte[] byteContent = signatureContent .getBytes( StandardCharsets.UTF_8);  // 将签名内容转换为字节码
    byte[] macResult = mac.doFinal( byteContent); // 从签名内容中获取签名结果
    String calSignature = Base64.getEncoder().encodeToString( macResult);  // 将签名结果通过 Base64 转换为字符串
    // signature 是请求消息体 signature 字段内容
    if ( calSignature.equals(reportReqVO.getSignature())) {
      // 签名校验成功，执行下一步骤
      return true;
    }
    return false;
  }

  /**
   * 解密dlp上报数据
   */
  public static String decryptData(String encryptionKey, String data) {

    // 对密文进行 BASE64 解码
    byte[] encryptStr = Base64.getDecoder().decode(data);
    try {
      encryptStr = Base64.getDecoder().decode(data);
    } catch (Exception e) {
      log.error("BASE64解码失败 encryptionKey {} , data {} , e {} ", encryptionKey, data, e);
      throw new BusinessException(ResponseCode.RESPONSE_RETURN_CODE_DECRYPT_ERROR);
    }

    // 使用AESKey进行解密
    Cipher cipher = null;
    try {
      cipher = Cipher.getInstance( "AES/ECB/PKCS5Padding");
    } catch (NoSuchAlgorithmException e) {
      log.error("AESKey进行解密失败 encryptionKey {} , data {} , e {} ", encryptionKey, data, e);
      throw new BusinessException(ResponseCode.RESPONSE_RETURN_CODE_DECRYPT_ERROR);
    } catch (NoSuchPaddingException e) {
      log.error("AESKey进行解密失败 encryptionKey {} , data {} , e {} ", encryptionKey, data, e);
      throw new BusinessException(ResponseCode.RESPONSE_RETURN_CODE_DECRYPT_ERROR);
    }
    byte[] byteKey = encryptionKey.getBytes( StandardCharsets.UTF_8);  // secretKey 是同步参数配置的加密秘钥
    SecretKeySpec secretKeySpec = new SecretKeySpec( byteKey , "AES");
    try {
      cipher.init( 2, secretKeySpec );
    } catch (InvalidKeyException e) {
      log.error("AESKey进行解密[cipher.init]失败 encryptionKey {} , data {} , e {} ", encryptionKey, data, e);
      throw new BusinessException(ResponseCode.RESPONSE_RETURN_CODE_DECRYPT_ERROR);
    }
    byte[] bytes = new byte[0];
    try {
      bytes = cipher.doFinal(encryptStr);
    } catch (IllegalBlockSizeException e) {
      log.error("AESKey进行解密[cipher.doFinal]失败 encryptionKey {} , data {} , e {} ", encryptionKey, data, e);
      throw new BusinessException(ResponseCode.RESPONSE_RETURN_CODE_DECRYPT_ERROR);
    } catch (BadPaddingException e) {
      log.error("AESKey进行解密[cipher.doFinal]失败 encryptionKey {} , data {} , e {} ", encryptionKey, data, e);
      throw new BusinessException(ResponseCode.RESPONSE_RETURN_CODE_DECRYPT_ERROR);
    }
    // 去掉 rand_msg 头部的16个随机字节，剩余的部分即为明文内容 msg
    return StringUtils.substringAfter(new String(bytes, StandardCharsets.UTF_8), "&");
  }
}
